using System;
using System.Collections.Generic;
using Xunit;
using WenYu.Core.Lexer;
using WenYu.Core.Parser;

namespace WenYu.Tests.DocumentValidation;

/// <summary>
/// 文档04-控制流.md的示例验证测试
/// </summary>
public class Doc04ControlFlowValidation
{
    private List<Token> Tokenize(string source)
    {
        var lexer = new WenYuLexer(source);
        return lexer.Tokenize();
    }

    private Program Parse(string source)
    {
        var lexer = new WenYuLexer(source);
        var tokens = lexer.Tokenize();
        var parser = new WenYuParser(tokens);
        return parser.Parse();
    }

    #region 条件分支测试

    [Fact]
    public void Example1_SimpleCondition()
    {
        var source = @"整型 分数 是 85。
若 分数 不《 60 则{
    输出（""及格了！""）。
}";

        var tokens = Tokenize(source);
        Assert.NotEmpty(tokens);
        var ast = Parse(source);
        Assert.NotNull(ast);
    }

    [Fact]
    public void Example2_IfElse()
    {
        var source = @"整型 年龄 是 10。
若 年龄 不《 18 则{
    输出（""成年人""）。
}余{
    输出（""未成年人""）。
}";

        var tokens = Tokenize(source);
        Assert.NotEmpty(tokens);
        var ast = Parse(source);
        Assert.NotNull(ast);
    }

    [Fact]
    public void Example3_IfElseIfElse()
    {
        var source = @"整型 分数 是 85。
若 分数 不《 90 则{
    输出（""优秀""）。
}又 分数 不《 80 则{
    输出（""良好""）。
}又 分数 不《 70 则{
    输出（""中等""）。
}又 分数 不《 60 则{
    输出（""及格""）。
}余{
    输出（""不及格""）。
}";

        var tokens = Tokenize(source);
        Assert.NotEmpty(tokens);
        var ast = Parse(source);
        Assert.NotNull(ast);
    }

    [Fact]
    public void Example4_NestedCondition()
    {
        var source = @"整型 年龄 是 15。
真假 有学生证 是 真真。
若 年龄 《 18 则{
    输出（""未成年人""）。
    若 有学生证 则{
        输出（""门票半价""）。
    }余{
        输出（""无学生证""）。
    }
}余{
    输出（""成年人""）。
}";

        var tokens = Tokenize(source);
        Assert.NotEmpty(tokens);
        var ast = Parse(source);
        Assert.NotNull(ast);
    }

    #endregion

    #region 循环控制测试

    [Fact]
    public void Example5_WhileLoop()
    {
        var source = @"整型 计数 是 1。
若 计数 不》 5 复{
    输出（""第 "" + 计数的文字 + "" 次""）。
    计数++。
}";

        var tokens = Tokenize(source);
        Assert.NotEmpty(tokens);

        var tokenValues = new List<string>();
        foreach (var token in tokens)
        {
            if (!string.IsNullOrWhiteSpace(token.Value))
                tokenValues.Add(token.Value);
        }

        Assert.Contains("复", tokenValues);

        var ast = Parse(source);
        Assert.NotNull(ast);
    }

    [Fact]
    public void Example6_DoWhileLoop()
    {
        var source = @"整型 计数 是 1。
复{
    输出（""第 "" + 计数的文字 + "" 次""）。
    计数++。
}若 计数 不》 5 续。";

        var tokens = Tokenize(source);
        Assert.NotEmpty(tokens);

        var tokenValues = new List<string>();
        foreach (var token in tokens)
        {
            if (!string.IsNullOrWhiteSpace(token.Value))
                tokenValues.Add(token.Value);
        }

        Assert.Contains("续", tokenValues);

        var ast = Parse(source);
        Assert.NotNull(ast);
    }

    [Fact]
    public void Example7_CountingLoopSimple()
    {
        var source = @"复 1 至 5 {
    输出（几的文字）。
}";

        var tokens = Tokenize(source);
        Assert.NotEmpty(tokens);

        var tokenValues = new List<string>();
        foreach (var token in tokens)
        {
            if (!string.IsNullOrWhiteSpace(token.Value))
                tokenValues.Add(token.Value);
        }

        Assert.Contains("至", tokenValues);
        Assert.Contains("几", tokenValues);

        var ast = Parse(source);
        Assert.NotNull(ast);
    }

    [Fact]
    public void Example8_CountingLoopWithStep()
    {
        var source = @"复 数 从 0 至 10 步 2 {
    输出（数的文字）。
}";

        var tokens = Tokenize(source);
        Assert.NotEmpty(tokens);

        var tokenValues = new List<string>();
        foreach (var token in tokens)
        {
            if (!string.IsNullOrWhiteSpace(token.Value))
                tokenValues.Add(token.Value);
        }

        Assert.Contains("从", tokenValues);
        Assert.Contains("至", tokenValues);
        Assert.Contains("步", tokenValues);

        var ast = Parse(source);
        Assert.NotNull(ast);
    }

    [Fact]
    public void Example9_ReverseCountingLoop()
    {
        var source = @"复 数 从 10 至 1 步 -1 {
    输出（数的文字）。
}";

        var tokens = Tokenize(source);
        Assert.NotEmpty(tokens);
        var ast = Parse(source);
        Assert.NotNull(ast);
    }

    [Fact]
    public void Example10_ArrayIterationLoop()
    {
        var source = @"整型组 分数 是 【85, 92, 78, 95, 88】。
输出（""所有分数：""）。
复 分数 取 分 {
    输出（分的文字）。
}";

        var tokens = Tokenize(source);
        Assert.NotEmpty(tokens);

        var tokenValues = new List<string>();
        foreach (var token in tokens)
        {
            if (!string.IsNullOrWhiteSpace(token.Value))
                tokenValues.Add(token.Value);
        }

        Assert.Contains("取", tokenValues);

        var ast = Parse(source);
        Assert.NotNull(ast);
    }

    [Fact]
    public void Example11_ArrayAverageCalculation()
    {
        var source = @"整型组 分数 是 【85, 92, 78, 95, 88】。
整型 总和 是 0。
整型 计数 是 0。
复 分数 取 分 {
    总和 是 总和 + 分。
    计数++。
}
整型 平均 是 总和 ÷ 计数。
输出（""平均分："" + 平均的文字）。";

        var tokens = Tokenize(source);
        Assert.NotEmpty(tokens);
        var ast = Parse(source);
        Assert.NotNull(ast);
    }

    #endregion

    #region 复杂控制流测试

    [Fact]
    public void Example12_NestedLoops()
    {
        var source = @"复 1 至 3 {
    输出（""外层："" + 几的文字）。
    复 1 至 2 {
        输出（""  内层："" + 几的文字）。
    }
}";

        var tokens = Tokenize(source);
        Assert.NotEmpty(tokens);
        var ast = Parse(source);
        Assert.NotNull(ast);
    }

    [Fact]
    public void Example13_LoopWithCondition()
    {
        var source = @"复 1 至 10 {
    若 几 % 2 同 0 则{
        输出（""偶数："" + 几的文字）。
    }
}";

        var tokens = Tokenize(source);
        Assert.NotEmpty(tokens);
        var ast = Parse(source);
        Assert.NotNull(ast);
    }

    [Fact]
    public void Example14_ComplexControlFlow()
    {
        var source = @"整型 总分 是 0。
整型组 成绩 是 【85, 92, 78, 95, 88】。

复 成绩 取 分 {
    若 分 不《 90 则{
        总分 是 总分 + 10。
    }又 分 不《 80 则{
        总分 是 总分 + 5。
    }
}

若 总分 》 30 则{
    输出（""优秀学生""）。
}余{
    输出（""其他学生""）。
}";

        var tokens = Tokenize(source);
        Assert.NotEmpty(tokens);
        var ast = Parse(source);
        Assert.NotNull(ast);
    }

    #endregion

    #region 循环关键字测试

    [Fact]
    public void Example15_LoopKeywordRecognition()
    {
        var source = @"整型 数 是 0。
复 数 从 1 至 10 步 1 {
    输出（数的文字）。
}";

        var tokens = Tokenize(source);
        Assert.NotEmpty(tokens);

        var tokenValues = new List<string>();
        foreach (var token in tokens)
        {
            if (!string.IsNullOrWhiteSpace(token.Value))
                tokenValues.Add(token.Value);
        }

        // Verify all loop keywords are recognized
        Assert.Contains("复", tokenValues);
        Assert.Contains("从", tokenValues);
        Assert.Contains("至", tokenValues);
        Assert.Contains("步", tokenValues);
    }

    #endregion
}
